#include <cstdlib>
#include <cassert>
#include <list>
#include <string>
#include <vector>
#include <deque>
#include <thread>

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "tlbtree/include/tlbtree.h"

namespace myslm {


#ifndef KEYTYPE
    using _key_t = uint64_t;
#else
    using _key_t = KEYTYPE;
#endif

using std::string;
using std::vector;
enum ReqType {PUT, UPDATE, DELETE};

inline size_t file_size(const char *fname) {
    struct stat buffer; stat(fname, &buffer);
    return buffer.st_size;
}

inline bool folder_exist(const char *fname) {
    struct stat buffer;
    return stat(fname, &buffer) == 0 && S_ISDIR(buffer.st_mode);
}

// Request meta data: 8 Bytes
struct Request {
    uint8_t op    : 6;
    uint8_t stale : 1;
    uint8_t hot   : 1;
    uint16_t crc;
    uint32_t val_size;
    char keyvalue[0];
    // key size: 8 Bytes
    // val size: variable
    inline uint32_t Length() {
        return sizeof(Request) + 8 + val_size;
    }
};

struct SLMOpt {
    std::string dbdir;   // data directory
    std::string nvmdir;  // NVM directory 
    uint64_t nvmsize  = 512UL * 1024 * 1024;  // NVM capaicty        : byte unit
};

class MySLM {
private:
    tlbtree::TLBtree * global_index_;
    int log_fd_;
    uint64_t log_offset_;

public:
    MySLM(const SLMOpt &);
    
    ~MySLM();

    // insert a key value pair, sync or not to storage
    void Put(const _key_t k, const string & v, bool sync);

    // update a key value pair, sync or not to storage
    bool Update(const _key_t k, const string & v, bool sync);

    // delete the value associated with key k, sync or not to storage
    bool Delete(const _key_t k, bool sync);

    // get the value associated with key k
    bool Get(const _key_t k, string & v);

    // range query key value pairs with 
    int Scan(const _key_t k, int len, vector<string> & out);

private:
    uint64_t Append(Request * req, bool sync);
};

} // namespace dnskv